#include "engine.h"
#include <gl/glew.h>
#include <gl/wglew.h>
#include "rendersystem.h"
#include "json/json.h"
#include "core/timer.h"
#include "3rdparty/Leo/LeoAPI.h"
#include "3rdparty/soil/SOIL.h"
#include "input/input.h"
#include <d3d9.h>
#include <d3dx9.h>
#include "core/stringhelper.h"
#include "entity/scene.h"
#include "entity/game.h"

//#define dynamic_vb_size (32*(1 << 20))
#define dynamic_vb_size (1024*1024)


LGLContext g_lglContext;
HGLRC g_hglrc;


void rendersystem_t::init(HWND hwnd)
{
	if (!RSYS)
		RSYS=new rendersystem_t(hwnd);
}

void rendersystem_t::exit()
{
	if (RSYS)
		delete RSYS;

	RSYS=0;
}

void rendersystem_t::loadglobals()
{
	
	//vertexdeklaraciok
	json_object_t& declarations=*generate_json_map("render/vertexdeclarations.list");
	ASSERT(&declarations);

	for (uint32 n=0; n<declarations.size(); ++n)
	{
		json_array_t& decl=declarations[n].get_array();

		fixedvector<vertexelement_t,16> velist;
		for (uint32 m=0; m<decl.size(); ++m)
		{
			json_array_t& jelem=decl[m].get_array();
			stringhash h=jelem[0].get_hash();

			uint32 fajta=0;
			if (h=="pos")
				fajta=VDECL_POS;
			else if (h=="color")
			{
				fajta=VDECL_COLOR;
			}
			else if (h=="normal")
			{
				fajta=VDECL_NORMAL;
			}
			else if (h=="tangent")
			{
				fajta=VDECL_TANGENT;
			}
			else if (h=="uv")
			{
				fajta=VDECL_UV;
			}
			vertexelement_t ve(jelem[2].get_int(),jelem[1].get_hash(),fajta);
			velist.push_back(ve);
		}

		stringhash name=declarations.pair_list[n].key;
		vertexdeclaration_t* vd=vertexdeclarations.allocate(name);
		vd->generate(name,&velist[0],velist.size());
	}

	delete & declarations;

	//shaders
	WIN32_FIND_DATA find_data;
	HANDLE file_search;
	vector<string> shaderlist;
	file_search=FindFirstFile("render/shaders/*.vsh", &find_data);
	string shaderfolder=string("render/shaders/");
	if (INVALID_HANDLE_VALUE!=file_search)
	{
		do
		{
			shaderlist.push_back(stringhelper::remove_extension(string(find_data.cFileName)));
		} while (FindNextFile(file_search, &find_data));
	}


	for (unsigned n=0; n<shaderlist.size(); ++n)
	{
		shader_t* sh=shaders.allocate(stringhash::get(shaderlist[n]));
		sh->generate(shaderfolder+shaderlist[n]);
	}

	//materials
	json_object_t& matlist=*generate_json_map("render/materials.list");
	ASSERT(&matlist);

	for (uint32 n=0; n<matlist.size(); ++n)
	{
		rendermaterial_t* mat=materials.allocate(matlist.pair_list[n].key);
		json_object_t& decl=matlist[n].get_object();

		mat->shader=get_shader(decl["shader"]->get_hash());
		mat->vdecl=get_vdecl(decl["vdecl"]->get_hash());
		json_object_t& renderstates=decl["renderstates"]->get_object();
		mat->rsb.alphatest=renderstates["alphatest"]->get_bool();
		mat->rsb.cull=renderstates["cull"]->get_bool();
		mat->rsb.blendfunc.sfactor=GL_SRC_ALPHA;
		mat->rsb.blendfunc.dfactor=GL_ONE_MINUS_SRC_ALPHA;
		mat->rsb.depthmask=renderstates["depthmask"]->get_bool();

		if (!renderstates["blendfunc"])
			continue;
		json_object_t& blendfunc=renderstates["blendfunc"]->get_object();
		if (&blendfunc)
		{
			stringhash sfactor=blendfunc["sfactor"]->get_hash();

			if (sfactor=="SRC_ALPHA")
				mat->rsb.blendfunc.sfactor=GL_SRC_ALPHA;
			else if (sfactor=="ONE")
				mat->rsb.blendfunc.sfactor=GL_ONE;


			else
				mat->rsb.blendfunc.sfactor=GL_SRC_ALPHA;

			stringhash dfactor=blendfunc["dfactor"]->get_hash();

			if (dfactor=="ONE_MINUS_SRC_ALPHA")
				mat->rsb.blendfunc.dfactor=GL_ONE_MINUS_SRC_ALPHA;
			else if (dfactor=="ONE_MINUS_SRC_COLOR")
				mat->rsb.blendfunc.dfactor=GL_ONE_MINUS_SRC_COLOR;
			else if (dfactor=="ONE")
				mat->rsb.blendfunc.dfactor=GL_ONE;
			else
				mat->rsb.blendfunc.dfactor=GL_ONE_MINUS_SRC_ALPHA;
		}
	}

	delete & matlist;


	global_shader_data.world_mtx.axis(3).set(0,-6,30);

	whitetextureid=get_texture("textures/white")->hwid;

	glGenSamplers(1,&globalsamplerstateid);


	int p=glGetError();
	GLASSERT;

}
void rendersystem_t::set_object_data()
{
//	glBindBuffer(GL_UNIFORM_BUFFER,globalshaderdataid);
	glBufferSubData(GL_UNIFORM_BUFFER,offsetof(global_shader_data_t,world_mtx),sizeof(float4x4)+sizeof(float4),&global_shader_data.world_mtx);
}

void rendersystem_t::set_object_world_matrix(const float4x4& mtx)
{
	glBufferSubData(GL_UNIFORM_BUFFER,offsetof(global_shader_data_t,world_mtx),sizeof(float4x4),&mtx);
}
void rendersystem_t::flushbuffers()
{
	text_array.clear();
	line_array.clear();
	renderobjects.clear();
	custom_renderobjects.clear();
}

float3 get_bird_world_pos()
{
	if (!leodevice_t::device_present)
		return(float3(0,0,0));

	double px,py,pz,rx,ry,rz;
	leoGetBirdPosition(&px,&py,&pz,&rx,&ry,&rz);

	float stereo_focus_distance=GAME->scene ? GAME->scene->renderPlaneDist : 50;
	float3 p((float)px,(float)py,(float)pz);

	const float4x4& cammtx=RSYS->global_shader_data.camera_mtx;

	p.z=2-p.z;
	p*=stereo_focus_distance;
	p=mul4x3(p,cammtx);
	return p;
}

float sorrend=-1;
void rendersystem_t::render(rendercontext_t* ctx/* =NULL */)
{
	global_shader_data.stereo_direction.set(0,0);
	if (INPSYS->keyboard.key_pressed(DIK_Q))
	{
		sorrend=-sorrend;
	}

	//set global data
	int rendercount=1;
	float stereo_focus_distance=20;
	float2 eye[2];
	eye[0].set(0,0);
	eye[1].set(0,0);
	int eyeindex=0;

	if (leodevice_t::device_present)
	{
		stereo_focus_distance=GAME->scene->renderPlaneDist;
		rendercount=lglGetRenderCount(g_lglContext);
		double e[6];
		double g[2];
		if (leoIsStereoSwitchedOn())
		{
			leoGetEyesPosition(e,e+1,e+2,e+3,e+4,e+5);
			g[0]=0.5*(e[0]+e[3]);
			g[1]=0.5*(e[1]+e[4]);
			eye[0].x=(float)(e[0]-g[0]);
			eye[0].y=(float)(e[1]-g[1]);
			eye[1].x=(float)(e[3]-g[0]);
			eye[1].y=(float)(e[4]-g[1]);
		}
	}
	float4x4 origcammtx=global_shader_data.camera_mtx;

	glClearDepth(1);
	static float3 lb(0,0,0),lt(0,0,0),rb(0,0,0),fo(0,0,0);

	for (unsigned n=0; n<custom_renderobjects.size(); ++n)
	{
		custom_renderobjects[n]->setupbuffers();
	}

	setup_textdraw();
	setup_linedraw();


	for (int renderpass=0; renderpass<rendercount; ++renderpass)
	{
		if (leodevice_t::device_present)
		{
			captureisvan=false;
			if (!strcmp(lglGetRenderName(g_lglContext,renderpass),"Self"))
			{
				global_shader_data.stereo_direction=eye[eyeindex++];
			}
			else
			{
				captureisvan=true;
			}

			double lglprojmat[16];
			lglStartRender(g_lglContext,renderpass,lglprojmat);
			LGLProjection f;
			lglGetProjection(g_lglContext,renderpass,&f);


			float4x4 tekero;
			tekero.identity();

			if (captureisvan)
			{
				tekero.axis(2).set(-f.focusX,-f.focusY,f.focusZ);
				tekero.normalize();
			}

			float4x4 newcammtx=origcammtx;

			newcammtx.translate()+=2*stereo_focus_distance*newcammtx.axis(2);
			float4x4 viewmtx;
			newcammtx.axis(2)*=-1;
			viewmtx.invert(newcammtx);
			viewmtx.scale(1/stereo_focus_distance);
			viewmtx.translate()/=stereo_focus_distance;

			for (int n=0; n<16; ++n)
				projection_matrix.m[n]=(float)lglprojmat[n];

			float4x4 tmpmtx; tmpmtx.mul(tekero,origcammtx);
			tmpmtx.axis(3)=origcammtx.axis(3);
			global_shader_data.camera_mtx=tmpmtx;
			global_shader_data.viewproj_mtx.mul(viewmtx,projection_matrix);
			global_shader_data.proj_mtx=projection_matrix;
		}	
		else
		{
			projection_matrix=get_projection_matrix(fov,1/aspect,0.1f,100.0f);
			float4x4 viewmtx;
			viewmtx.invert(global_shader_data.camera_mtx);
			viewmtx.scale(1/GAME->scene->renderPlaneDist);
			viewmtx.translate()/=GAME->scene->renderPlaneDist;

			global_shader_data.camera_mtx=origcammtx;
			global_shader_data.viewproj_mtx.mul(viewmtx,projection_matrix);
			global_shader_data.proj_mtx=projection_matrix;

			glClear(GL_DEPTH_BUFFER_BIT);
		}
		GLASSERT;

		glBindBuffer(GL_UNIFORM_BUFFER,globalshaderdataid);
		GLASSERT;
		glBufferSubData(GL_UNIFORM_BUFFER,0,sizeof(global_shader_data),&global_shader_data);
		global_shader_data.camera_mtx=origcammtx;
		GLASSERT;
		glDepthMask(true);
		GLASSERT;
		glClearColor(0.0f,0.0f,0.05f,1);
		GLASSERT;
		glEnable(GL_DEPTH_TEST);

		GLASSERT;
		glEnable(GL_CULL_FACE);
		glCullFace(GL_FRONT);
		GLASSERT;
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		GLASSERT;

		for (unsigned n=0; n<renderobjects.size(); ++n)
		{
			global_shader_data.model_color=renderobjects[n]->object_color;
			GLASSERT;
			set_object_data();
			GLASSERT;
			renderobjects[n]->draw();
#ifdef LEO_DESIGNER
			if (renderobjects[n]->selected)
			{
				glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
				selection_on=true;
				renderobjects[n]->draw();
				glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
				selection_on=false;
			}
#endif
			GLASSERT;
		}
		GLASSERT;

		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_COLOR);
		GLASSERT;
		glDepthMask(false);
		GLASSERT;
		for (unsigned n=0; n<custom_renderobjects.size(); ++n)
		{
			custom_renderobjects[n]->onrender();
		}
		glBlendFunc(GL_SRC_ALPHA,GL_ONE);
		glDisable(GL_DEPTH_TEST);
		draw_lines();
		if (textdraw_enabled)
			draw_texts();

		glDepthMask(true);

	}
	if (leodevice_t::device_present)
		lglFinishRender(g_lglContext);
	else
		SwapBuffers(hdc);

	dynamic_offset=0;
	flushbuffers();

	ZeroMemory(global_shader_data.light,sizeof(global_shader_data.light));
	num_lights=0;
}

rendersystem_t::~rendersystem_t()
{
	glDeleteSamplers(1,&globalsamplerstateid);
	glDeleteBuffers(1,&globalshaderdataid);
	quadib.release();
	glDeleteBuffers(1,&dynamic_vb_id);
	textures.flush();
	vertexdeclarations.flush();
	shaders.flush();
	materials.flush();

	for (unsigned n=0; n<objects.size(); ++n)
	{
		renderhierarchy_t* h=objects.get(n);
		for (unsigned nodeindex=0; nodeindex<h->node_buf.size(); ++nodeindex)
		{
			rendermesh_t* mesh=h->node_buf[nodeindex].mesh;
			if (mesh)
				delete mesh;
		}

		delete h->animation;
	}
	objects.flush();
	if (leodevice_t::device_present)
	{
		leoSetStereo(false);
		lglDeleteContext(g_lglContext);
	}
	wglDeleteContext(g_hglrc);
}

#include "assimploader.h"
//#define NATIVE_LOADSAVE
bool rendersystem_t::get_3d_object(renderhierarchy_t& h, const stringhash& name)
{
	renderhierarchy_t* object=objects.get(name);

	if (!object) //lehet hogy meg nincs betoltve
	{
#ifdef NATIVE_LOADSAVE
		string nativefilename=stringhelper::remove_extension(name.c_str())+".leo3d";

		file_t f(nativefilename.c_str(),"rb");

		if (f.is_open())
		{
			object=objects.allocate(name);
			object->load();
			f.close();
		}
		else
#endif
		{
			string filename=stringhelper::remove_extension(name.c_str())+".dae";
			vector<rendernode_t> node;
			vector<animation_t> anim;
			if (load_object(node,anim,filename.c_str()))
			{
				object=objects.allocate(name);
				object->node_buf=node;
				object->animation=0;

				if (anim.size())
				{
					object->animation=new animationcontainer_t;
					object->animation->anims=anim;
				}
			}
#ifdef NATIVE_LOADSAVE
	#ifdef LEO_DESIGNER
			if (object)
				object->save();
	#endif
#endif
		}
	}

	if (!object)
		return false;
	h=*object;
	return false;
}


rendertexture_t* rendersystem_t::get_texture(const stringhash& name)
{
	rendertexture_t* tex=textures.get(name);

	if (!tex)
	{
		int width,height,channel;
		uint8* texturebuffer=SOIL_load_image((string(name.c_str())+".dds").c_str(),&width,&height,&channel,SOIL_LOAD_AUTO);

		if (!texturebuffer)
			return 0;

		uint32 textid= SOIL_load_OGL_texture(
			(string(name.c_str())+".dds").c_str(),
			SOIL_LOAD_AUTO,
			SOIL_CREATE_NEW_ID,
//			SOIL_FLAG_POWER_OF_TWO |
			//SOIL_FLAG_MIPMAPS |
			//| SOIL_FLAG_MULTIPLY_ALPHA
			//| SOIL_FLAG_COMPRESS_TO_DXT
			SOIL_FLAG_DDS_LOAD_DIRECT |SOIL_FLAG_TEXTURE_REPEATS
			//| SOIL_FLAG_NTSC_SAFE_RGB
			//| SOIL_FLAG_CoCg_Y
			//| SOIL_FLAG_TEXTURE_RECTANGLE
			);

		delete [] texturebuffer;

		if (textid==0)
		{
			return 0;
		}

		tex=textures.allocate(name);
		tex->width=width;
		tex->height=height;
		tex->hwid=textid;

	}

	return tex;
}

hashcontainer_t<rendertexture_t,1024,1024> rendersystem_t::textures;
hashcontainer_t<shader_t,1024,1024> rendersystem_t::shaders;
hashcontainer_t<rendermaterial_t,1024,1024> rendersystem_t::materials;
hashcontainer_t<vertexdeclaration_t,16,16> rendersystem_t::vertexdeclarations;
hashcontainer_t<renderhierarchy_t,16384,16384> rendersystem_t::objects;

rendersystem_t* RSYS=NULL;

void rendersystem_t::set_light(const float3& center, float radius, const float4& color)
{
	if (num_lights<MAX_LIGHT_COUNT)
	{
		global_shader_data.light[num_lights].centerradius.set(center.x,center.y,center.z,radius);
		global_shader_data.light[num_lights].color=color;
		++num_lights;
	}
}

rendersystem_t::rendersystem_t(HWND hwnd)
{
	captureisvan=false;
	num_lights=0;
#ifdef LEO_DESIGNER
	selection_on=false;
#endif
	textdraw_enabled=true;
	main_hwnd=hwnd;
	global_shader_data.directional_light.set(-1,1,-.5f,0);
	normalize((float3&)global_shader_data.directional_light);
	hdc = ::GetDC(hwnd);

	PIXELFORMATDESCRIPTOR pfd = { 
		sizeof(PIXELFORMATDESCRIPTOR),   // size of this pfd  
		1,                     // version number  
		PFD_DRAW_TO_WINDOW |   // support window  
		PFD_SUPPORT_OPENGL |   // support OpenGL  
		PFD_DOUBLEBUFFER,      // double buffered  
		PFD_TYPE_RGBA,         // RGBA type  
		32,                    // 32-bit color depth  
		0, 0, 0, 0, 0, 0,      // color bits ignored  
		0,                     // no alpha buffer  
		0,                     // shift bit ignored  
		0,                     // no accumulation buffer  
		0, 0, 0, 0,            // accum bits ignored  
		24,                    // 32-bit z-buffer  
		8,                     // no stencil buffer  
		0,                     // no auxiliary buffer  
		PFD_MAIN_PLANE,        // main layer  
		0,                     // reserved  
		0, 0, 0                // layer masks ignored  
	}; 
	int  pixelFormat; 

	pixelFormat = ChoosePixelFormat(hdc, &pfd); 
	SetPixelFormat(hdc, pixelFormat, &pfd);

	g_hglrc=wglCreateContext(hdc);
	DWORD lasterr=GetLastError();
	char errorstr[16384];
	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lasterr, 0, errorstr, 255, NULL);
	wglMakeCurrent(hdc,g_hglrc);
	GLenum err=glewInit();
//	wglSwapIntervalEXT(1);

	on_resize();//hwnd);
	fov=DEG2RAD*50;


	leodevice_t::device_present=leoInitialize();
	if (leodevice_t::device_present)
	{
		lglInitialize();
//		leoSetStereo(false);
		g_lglContext=lglCreateContext(hdc,g_hglrc);
	}

	glEnable(GL_BLEND);

	uint32 error=0;
	loadglobals();
	error+=glGetError();

	projection_matrix=get_projection_matrix(DEG2RAD*30,1/aspect,1,100000);
	error+=glGetError();

	//global shader data
	glGenBuffers(1,&globalshaderdataid);
	GLASSERT;
	glBindBuffer(GL_UNIFORM_BUFFER,globalshaderdataid);
	GLASSERT;
	glBufferData(GL_UNIFORM_BUFFER,sizeof(global_shader_data_t),&global_shader_data,GL_STATIC_DRAW);
	GLASSERT;
	//	glBindBuffer(GL_UNIFORM_BUFFER,0);
	glBindBufferRange(GL_UNIFORM_BUFFER,0,globalshaderdataid,0,sizeof(global_shader_data_t));
	GLASSERT;

	quadib.init(16384*6);
	uint16* ib =quadib.lock();
	for (uint32 n=0; n<16384; ++n)
	{
		ib[6*n]=4*n;
		ib[6*n+1]=4*n+1;
		ib[6*n+2]=4*n+2;
		ib[6*n+3]=4*n;
		ib[6*n+4]=4*n+2;
		ib[6*n+5]=4*n+3;
	}
	quadib.unlock();
	GLASSERT;

	glGenBuffers(1,&dynamic_vb_id);
	GLASSERT;
	glBindBuffer(GL_ARRAY_BUFFER,dynamic_vb_id);
	GLASSERT;
	glBufferData(GL_ARRAY_BUFFER,dynamic_vb_size,NULL,GL_DYNAMIC_DRAW);
	GLASSERT;
	dynamic_offset=0;

	glAlphaFunc(GL_LESS,0.5f);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	textvb.init_dynamic(get_vdecl("font"));
	linevb.init_dynamic(get_vdecl("poscolor"));

}

void* rendersystem_t::lock_dynamic_vb(uint32 size,uint32& offset)
{
	GLASSERT;
	glBindBuffer(GL_ARRAY_BUFFER,dynamic_vb_id);
	GLASSERT;
	void* ret=glMapBufferRange(GL_ARRAY_BUFFER,dynamic_offset,size,GL_MAP_WRITE_BIT);
	GLenum p=glGetError();
	GLASSERT;
	offset=dynamic_offset;
	dynamic_offset+=size;
	ASSERT(dynamic_offset<dynamic_vb_size);
	return ret;
}

void rendersystem_t::unlock_dynamic_vb()
{
	glBindBuffer(GL_ARRAY_BUFFER,dynamic_vb_id);
	glUnmapBuffer(GL_ARRAY_BUFFER);
}

void rendersystem_t::setup_linedraw()
{
	if (!line_array.size())
		return;

	debug_line_t* ptr=(debug_line_t*)linevb.lock(line_array.size()*2);
	memcpy(ptr,&line_array[0],line_array.size()*sizeof(debug_line_t));
	linevb.unlock();
}

void rendersystem_t::setup_textdraw()
{
	if (!text_array.size())
		return;

	unsigned& charnum=textcharnum;
	charnum=0;
	for (unsigned n=0; n<text_array.size(); ++n)
		charnum+=text_array[n].text.size();

	vertexbuffer_t& vb=textvb;

	struct font_vertex_t
	{
		float3 pos;
		float4 color;
		float2 uv;
	};

	font_vertex_t* ptr=(font_vertex_t*)vb.lock(charnum*4);

	for (unsigned textindex=0;textindex<text_array.size();++textindex)
	{
		const float ratex=text_array[textindex].size*2.0f/screen_size_horizontal;
		const float ratey=text_array[textindex].size*2.0f/screen_size_vertical;
		float x=text_array[textindex].x*2.0f/screen_size_horizontal-1;
		float y=1.0f-text_array[textindex].y*2.0f/screen_size_vertical;
		float depth=text_array[textindex].depth;
		const float4& color=text_array[textindex].color;
		for (unsigned charindex=0; charindex<text_array[textindex].text.size(); ++charindex,ptr+=4)
		{
			char ch=text_array[textindex].text[charindex];

			ptr[0].pos.x=x;
			ptr[0].pos.y=y;
			ptr[0].pos.z=depth;
			ptr[1].pos.x=x+ratex;
			ptr[1].pos.y=y;
			ptr[1].pos.z=depth;
			ptr[2].pos.x=x+ratex;
			ptr[2].pos.y=y-ratey;
			ptr[2].pos.z=depth;
			ptr[3].pos.x=x;
			ptr[3].pos.y=y-ratey;
			ptr[3].pos.z=depth;

			x+=ratex;

			float u=(ch%16)/16.0f;
			float v=(ch/16)/16.0f;

			ptr[0].uv.x=u;
			ptr[0].uv.y=v;
			ptr[1].uv.x=u+1/16.0f;
			ptr[1].uv.y=v;
			ptr[2].uv.x=u+1/16.0f;
			ptr[2].uv.y=v+1/16.0f;
			ptr[3].uv.x=u;
			ptr[3].uv.y=v+1/16.0f;

			ptr[0].color=color;
			ptr[1].color=color;
			ptr[2].color=color;
			ptr[3].color=color;

		}
	}
	vb.unlock();

}

void rendersystem_t::draw_lines()
{
	if (!line_array.size())
		return;

	get_material("line")->set();
	linevb.set();
	glDrawArrays(GL_LINES,0,line_array.size()*2);
	
}

void rendersystem_t::draw_texts()
{
	if (!text_array.size())
		return;
	shader_t* sh=get_shader("font"); sh->set();
	textvb.set();
	quadib.set();
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, get_texture("textures/fonts/arial")->hwid);
	glDrawElements(GL_TRIANGLES,textcharnum*6,GL_UNSIGNED_SHORT,0);
}

void rendersystem_t::on_resize(bool caption)//HWND hwnd)
{
	HWND hwnd=main_hwnd;
	RECT r;
	GetClientRect(hwnd,&r);
	glViewport(0,0,r.right,r.bottom);
	screen_size_horizontal=r.right;
	screen_size_vertical=r.bottom-15;

	aspect=(float)r.bottom/(float)r.right;
}


void print_screen(int x, int y, const string& str)//,const float4& color=float4(1,1,1,1),int size=32,float depth=0)
{
	RSYS->print(x,y,str);
}

void draw_line(const float3& s,const float3& e, const float4& c)
{
	RSYS->draw_line(s,e,c,c);
}

float get_aspect()
{
	return RSYS->aspect;
}
#include "script/script.h"
script_fn_registering_begin(input)
register_script_fn("void print_screen(int,int, const string& in)",print_screen);
register_script_fn("float get_aspect()",get_aspect);
register_script_fn("void draw_line(const float3& in,const float3& in, const float4& in)",draw_line);
register_script_fn("float3 get_bird_world_pos()",get_bird_world_pos);
script_fn_registering_end
